package com.sohu.sip.group.impl;

import org.jgroups.Channel;
import org.jgroups.JChannel;
import org.jgroups.blocks.RpcDispatcher;
import org.jgroups.stack.IpAddress;

import com.sohu.sip.group.Config;
import com.sohu.sip.group.client.impl.HashDispatcher;
import com.sohu.sip.group.util.StringUtil;


/**
 * 
 *
 */
public abstract class AbstractCacheRPCClient extends AbstractCacheRPC {

	private final static String CLINET_PROPERTIES_FILENAME = "/sipgroup-client.properties";
	
	private final Config config = new Config(CLINET_PROPERTIES_FILENAME);
	
	protected static Integer timeout=0;
	
	protected static boolean running=false;
	
//	//fow external 
//	private static boolean stoppicset=false;
	
	protected boolean autorestart=true;
	
//	private boolean supporting=true;
//	
//	private boolean saving=true;
	

	protected RpcDispatcher rpc;

	private Channel rpcChannel;

	protected IpAddress[] serverAddrs;

	private static final String DEFAULT_SERVER_IP = "192.168.105.168";

	private static final long DEFAULT_RPC_TIMEOUT = 10000;
	
	protected long rpcTimeout;
	
	protected HashDispatcher dispatcher;

	
	public void init() {

		rpcTimeout = StringUtil.parseLong(config.getProperty("cache.rpc.timeout"), DEFAULT_RPC_TIMEOUT).longValue();
		
		String RPC_GROUP = config.getProperty(RPC_GROUP_NAME_PROPERTIES);
		log.info("JavaGroups RPC Server RPC_GROUP="+RPC_GROUP);
		if(RPC_GROUP==null||"".equals(RPC_GROUP.trim()))
			throw new RuntimeException("JavaGroups RPC Server RPC_GROUP not permit null");
		
		String rpcProperties = getRpcProperties(config , false);		
		try {

			rpcChannel = new JChannel(rpcProperties);
			rpcChannel.setOpt(Channel.GET_STATE_EVENTS, Boolean.FALSE);
			rpcChannel.setOpt(Channel.SUSPECT, Boolean.TRUE);
			rpcChannel.setOpt(Channel.AUTO_RECONNECT, Boolean.TRUE);
			rpcChannel.setOpt(Channel.LOCAL, Boolean.FALSE);

			rpc = new RpcDispatcher(rpcChannel, null, null, null, true, true);
			rpcChannel.connect(RPC_GROUP);

//			String serverIp = config.getProperty("cache.rpc.server.ip");
//			if (serverIp == null) {
//				serverIp = DEFAULT_SERVER_IP;
//			}
//			int serverPort = StringUtil.parseInt(config.getProperty("cache.rpc.server.port"),
//					DEFAULT_RPC_PORT);

//			serverAddr = new IpAddress(serverIp, serverPort);
//
//			log.info("init() -RPC serverAddress : " + serverAddr);

			serverAddrs = initServerAddr();
			
			dispatcher = HashDispatcher.getInstance(serverAddrs.length);
			
			log.info("JavaGroups clustering support started successfully");
			running=true;
		} catch (Exception e) {
			throw new IllegalStateException("Initialization failed: " , e);
		}
	}
	
	private IpAddress[] initServerAddr(){
		int count = StringUtil.parseInt(config.getProperty("cache.rpc.server.count"));
		if(count==0){
			count = 1;
		}
		IpAddress[] serverAddrs = new IpAddress[count];
		String prefix = "cache.rpc.server.";
		for (int i = 0; i < count; i++) {
			String serverIp = config.getProperty(prefix+i+".ip");
			int serverPort = StringUtil.parseInt(config.getProperty(prefix+i+".port"),DEFAULT_RPC_PORT);
			IpAddress serverAddr = new IpAddress(serverIp, serverPort);
			
			serverAddrs[i] = serverAddr;
			
			log.info("init() -RPC serverAddress["+i+"] : " + serverAddr);
		}
		return serverAddrs;
	}

	public void destroy() {
		if (log.isInfoEnabled()) {
			log.info("JavaGroups shutting down...");
		}
		running=false;
		if(rpcChannel !=null){
			rpcChannel.close();
			rpcChannel = null;
		}
		if(rpc!=null){
			rpc.stop();
			rpc = null;
		}

		if (log.isInfoEnabled()) {
			log.info("JavaGroups shutdown complete.");
		}
	}

	public static boolean isRunning() {
		return running;
	}
	
	public static void setRunning(boolean running) {
		AbstractCacheRPCClient.running = running;
	}

	public RpcDispatcher getRpc() {
		return rpc;
	}
	
	/**
	 * @return Returns the autorestart.
	 */
	public boolean isAutorestart() {
		return autorestart;
	}
	
	/**
	 * @param autorestart The autorestart to set.
	 */
	public void setAutorestart(boolean autorestart) {
		this.autorestart = autorestart;
		log.info("setAutorestart(boolean) - autorestart : " + autorestart);
	}
}